package generators;

import java.util.ArrayList;

abstract public class GeneratorBase {

	/** Generate. */
	 abstract public Object _generate( String[] pArgs, boolean pThrow );
	 
	 public static final String IDS="ABCDEFGHIJKLMNOPQRSTUVWXY";

	 abstract public void _insert( String pText );
		  
	 abstract public void _insert( Object pObject );
		  
	  abstract public void _insert( int pInt );
	  
	  abstract public void _insert( long pLong );
	  
	  abstract public void _insert( short pShort );
	  
	  abstract public void _insert( byte pByte );
	  
	  abstract public void _insert( double pDouble );
	  
	  abstract public void _insert( float pFloat );
	  
	  abstract public void _insert( char pChar );
	  
	  abstract public void _insert( boolean pBoolean );

/*
 * final Fun1<A, B> cp1, final Fun1<B, Z> cp2
 * 
 * B b = cp1.apply(p1);
 * Z res = cpf.apply(b);
 * 
 */
	 public void genCallWithArgs(int count) {
		if (count == 0) {return;}
	 	for(int i=0; i<count-1 && i<25; i++){
	 		_insert("final Fun1<A, "+IDS.charAt(i+1)+"> p"+(i+1)+", "); 
	 	}
	 	_insert("final Fun1<A, "+IDS.charAt(count)+"> p"+(count));
	 }
	 
	 public void genComposeArgs(int count) {
		count --;
		if (count == 0) {return;}
	 	for(int i=0; i<count && i<25; i++){
	 		_insert("final Fun1<"+IDS.charAt(i)+", "+IDS.charAt(i+1)+"> cp"+(i+1)+", "); 
	 	}
	 	_insert("final Fun1<"+IDS.charAt(count)+", Z> cpf");	 	
	 }	 
	 
	 public void genCompose(int count) {
		if (count == 0) {return;}
		String last = "a";
	 	for(int i=1; i<count && i<25; i++){
	 		_insert(IDS.charAt(i)+" p"+i+" = cp"+i+".apply("+last+");");
	 		last = "p"+i;
	 	}
	 	_insert("Z res = cpf.apply("+last+");");
	 }
	  
	 public void genMatchArgs(int count) {
		count --;
		if (count < 0) {return;}
	 	for(int i=0; i<count && i<25; i++){
	 		_insert("final Fun1<"+IDS.charAt(i)+", Boolean> p"+(i+1)+", "); 
	 	}
	 	_insert("final Fun1<"+IDS.charAt(count)+", Boolean> p"+(count+1));	 	
	 }
	 
	 public void genMatchType(int count) {
		count --;
		if (count < 0) {return;}
	 	for(int i=0; i<count && i<25; i++){
	 		_insert("Fun1<"+IDS.charAt(i)+", Boolean> , "); 
	 	}
	 	_insert("Fun1<"+IDS.charAt(count)+", Boolean> ");	 	
	 }
	 
	 public void genMessagingArgs(int count) {
		count --;
		if (count < 0) {return;}
	 	for(int i=0; i<count && i<25; i++){
	 		_insert("final Class<"+IDS.charAt(i)+"> p"+(i+1)+", "); 
	 	}
	 	_insert("final Class<"+IDS.charAt(count)+"> p"+(count+1));	 	
	 }
	 
	 public void genMessagingTuple(int count) {
		count --;
		if (count < 0) {return;}
	 	for(int i=0; i<count && i<25; i++){
	 		_insert("Class<"+IDS.charAt(i)+"> , "); 
	 	}
	 	_insert("Class<"+IDS.charAt(count)+">" );	 	
	 }
	 
	 public void genPlaceHolderArgs(ArrayList list) {
	 	int i=0; int count = list.size() - 1;
	 	if (i<0 || count == 0) {return;}
	 	for(; i<count && i<25; i++){
	 		char letter = IDS.charAt(i);
	 		_insert("final ");
	 		if (list.get(i) != null) {
	 			_insert(letter+ " p" + (i+1) +", ");
	 		} else {
	 			_insert("PlaceHolder ph"+ (i+1) +", ");
	 		}
	 	}
	 	_insert("final ");
	 	if (list.get(i) != null) {
	 		_insert(IDS.charAt(i) + " p" + (count+1));
	 	} else {
	 		_insert("PlaceHolder ph"+ (count+1));
	 	}
	 }

	 public void genPHType(ArrayList list) {
	 	int phCount = 0; // how many Fun
	 	int i=0; int count = list.size() - 1;
	 	if (i<0 || count == 0) {return;}
	 	
	 	StringBuilder builder = new StringBuilder();
	 	builder.append("<");
	 	for(; i<count && i<25; i++){
	 		char letter = IDS.charAt(i);
	 		if (list.get(i) == null) {
	 			builder.append(letter+ ", ");
	 			phCount++;
	 		}
	 	}
	 	if (list.get(i) == null) {
	 		phCount++;
	 		builder.append(IDS.charAt(i) + ", ");
	 	} 
	 	builder.append("Z>");
	 	
	 	_insert("Fun"+phCount+builder.toString());
	 	
	 }

	 public void genTupleType(ArrayList list) {
	 	int phCount = 0; // how many Fun
	 	int i=0; int count = list.size() - 1;
	 	if (i<0 || count == 0) {return;}
	 	
	 	StringBuilder builder = new StringBuilder();
	 	builder.append("<");
	 	for(; i<count && i<25; i++){
	 		char letter = IDS.charAt(i);
	 		if (list.get(i) == null) {
	 			builder.append(letter+ ", ");
	 			phCount++;
	 		}
	 	}
	 	if (list.get(i) == null) {
	 		phCount++;
	 		builder.append(IDS.charAt(i));
	 	} else {
	 		if (builder.lastIndexOf(", ") == builder.length() -2) {
	 			builder.delete(builder.length()-2, builder.length());
	 		}
	 	}
	 	builder.append(">");
	 	
	 	_insert("Tuple"+phCount+builder.toString());
	 	
	 }
	
	 public void genTupleArg(ArrayList list) {
	 	int phCount = 0; // how many Fun
	 	int i=0; int count = list.size() - 1;
	 	if (i<0 || count == 0) {return;}
	 	
	 	StringBuilder builder = new StringBuilder();
	 	
	 	for(; i<count && i<25; i++){
	 		if (list.get(i) == null) {
	 			builder.append(" arg.p"+(i+1)+ ", ");
	 			phCount++;
	 		}
	 	}
	 	if (list.get(i) == null) {
	 		phCount++;
	 		builder.append(" arg.p"+(i+1));
	 	} else {
	 		if (builder.lastIndexOf(", ") == builder.length() -2) {
	 			builder.delete(builder.length()-2, builder.length());
	 		}
	 	}
	 	_insert(builder.toString());
	 	
	 }
	 
	 public void generatePHApply(ArrayList list) {
	 	int i=0; int count = list.size() - 1;
	 	if (i<0 || count == 0) {return;}
	 	StringBuilder builder = new StringBuilder();
	 	for(; i<count && i<25; i++){
	 		char letter = IDS.charAt(i);
	 		if (list.get(i) == null) {
	 			builder.append("final ");
	 			builder.append(letter+ " p" + (i+1) +", ");
	 		}
	 	}
	 	
	 	if (list.get(i) == null) {
	 		builder.append("final ");
	 		builder.append(IDS.charAt(i) + " p" + (count+1));
	 	} else {
	 		if (builder.lastIndexOf(", ") == builder.length() -2) {
	 			_insert(builder.substring(0,builder.length()-2));
	 			return;
	 		}
	 	}
	 	_insert(builder.toString());
	 }

	 public void genPHParams(int sp, int pp, int funSize) {
	 	if (sp!=0) {generateCParams(0, sp);_insert(",");}
	 	generateCParams(sp, pp+1);
	 	if(pp!=funSize-1) {_insert(",");generateCParams(pp+1, funSize);}
	 }

	 public void genPHTemplateType(int sp, int pp, int funSize) {
	 	generateFullTemplateType(sp, pp+1);
	 }

	 public void generateFullTemplateType(int start, int count) {
	 	for(int i=start; i<count && i<25; i++){
	 		char letter = IDS.charAt(i);
	 		_insert(letter +",");
	 	}
	 }

	 public void generateUptoTemplateType(int count) {
		 generateUptoTemplateType(0, count);
	 }
	 
	 public void generateUptoTemplateType(int start, int count) {
	 	for(int i=start; i<count && i<25; i++){
	 		char letter = IDS.charAt(i);
	 		_insert(letter);
	 		if (i+1!=count) {
	 			_insert(",");
	 		}
	 	}
	 }

	 public void generateFullTemplateType(int count) {
	 	generateFullTemplateType(0, count);
	 }

	 public void generatePlaceHolder(int start, int count, boolean finals) {
	 	int i=start+1;
	 	if (i<0 || count == 0) {return;}
	 	for(; i<count && i<25; i++){
	 		if (finals) {
	 			_insert("final ");
	 		}
	 		_insert("PlaceHolder ph" + i +", ");
	 	}
	 	if (finals) {
	 			_insert("final ");
	 		}
	 	_insert("PlaceHolder ph" + count);
	 }

	 public void generateApply(int start, int count, boolean finals) {
	 	int i=start+1;
	 	if (i<0 || count == 0) {return;}
	 	for(; i<count && i<25; i++){
	 		char letter = IDS.charAt(i-1);
	 		if (finals) {
	 			_insert("final ");
	 		}
	 		_insert(letter+ " p" + i +", ");
	 	}
	 	if (finals) {
	 			_insert("final ");
	 		}
	 	_insert(IDS.charAt(i-1) + " p" + count);
	 }

	 public void generateMethodClassParams(int count) {
	 	int i=2; // never use A
	 	if (i<0 || count == 0) {return;}
	 	for(; i<count && i<25; i++){
	 		char letter = IDS.charAt(i-1);
	 		_insert("final Class<");
	 		_insert(letter+ "> p" + i +", ");
	 	}
	 	_insert("final Class<");
	 	_insert(IDS.charAt(i-1) + "> p" + count);
	 }
	 
	 public void generateApply(int count, boolean finals) {
	 	generateApply(0, count, finals);
	 }

	 public void generateCParams(int start, int count) {
	 	for(int i=start+1; i<count && i<25; i++){
	 		_insert(" p" + i +", ");
	 	}
	 	_insert(" p" + count);
	 }

}
